home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 001a / mskrmsrc.zip / MSNPDI.ASM < prev    next >
Assembly Source File  |  1991-10-24  |  12KB  |  402 lines

  1.     NAME    MSNPDI
  2. ; File MSNPDI.ASM
  3. ; Packet Driver interface 
  4. ;
  5. ; Copyright (C) 1991, Trustees of Columbia University in the
  6. ;  City of New York.  Permission is granted to any individual or
  7. ;  institution to use, copy, or redistribute this software as long as
  8. ;  it is not sold for profit and this copyright notice is retained.
  9. ; Written by Joe R. Doupnik, Utah State University, 
  10. ;  jrd@cc.usu.edu, jrd@usu.Bitnet.
  11. ;
  12. ; Edit history
  13. ; Last edit
  14. ; 6 Sept 1991
  15.  
  16. getintv    equ    35h            ; DOS get interrupt vector to es:bx
  17. dos    equ    21h
  18. pdgetinfo    equ    1        ; Packet Driver functions
  19. pd_access     equ    2
  20. pd_release    equ    3
  21. pd_send        equ    4
  22. pd_get_address    equ    6
  23. eaddr_len    equ    6        ; length of an Ethernet address
  24. ETH_MSS        equ    534        ; Correlate with msntcp.h
  25.  
  26. link    struc                ; buffer link structure
  27.     flag    db    0        ; buffer use flag
  28.     bufnum    db    0        ; buffer write/read sequence number
  29.     count    dw    0        ; count of items to follow
  30. link    ends
  31. linksize equ    4            ; bytes in link structure
  32.  
  33. _TEXT    SEGMENT  WORD PUBLIC 'CODE'
  34. _TEXT    ENDS
  35. _DATA    SEGMENT  WORD PUBLIC 'DATA'
  36. _DATA    ENDS
  37. CONST    SEGMENT  WORD PUBLIC 'CONST'
  38. CONST    ENDS
  39. _BSS    SEGMENT  WORD PUBLIC 'BSS'
  40. _BSS    ENDS
  41. DGROUP    GROUP    CONST, _BSS, _DATA
  42.     ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP
  43.  
  44. _DATA      SEGMENT
  45.     extrn     _pktbuf_wrote:word, _pktwnum:byte
  46. pdsignature db    'PKT DRVR'        ; signature of a Packet Driver
  47. if_type    dw    0            ; interface type
  48. if_class db    0            ; interface class
  49. if_num    db    0            ; interface number
  50. notype    db    1,2            ; dummy packet type
  51. notypelen equ    $-notype        ; length of type field for notype
  52. pktbufoff dw    0            ; offset of packet buffer
  53. pendingpkt dw    0            ; offset of packet being confirmed
  54. _DATA      ENDS
  55.  
  56. _TEXT    segment
  57.  
  58. pktdrvr    proc    near            ; Packet Driver interrupt invokation
  59. PKTDRVI:int    60h        ; Interrupt number modified by startup code
  60.     ret
  61. pktdrvr    endp
  62.  
  63. ; pdinit(ðeraddress)
  64.  
  65.     public    _pdinit
  66. _pdinit    proc    near
  67.     push    bp
  68.     mov    bp,sp
  69.     push    es
  70.     push    si
  71.     push    di
  72.     push    ds
  73.     mov    ax,dgroup
  74.     mov    ds,ax
  75.     mov    ax,[bp+4+0]        ; get offset of pktbuf
  76.     mov    pktbufoff,ax        ; save locally
  77.  
  78.     mov    cx,60h            ; interrupt range
  79. pdinit1:mov    ah,getintv        ; get interrupt vector
  80.     mov    al,cl            ; vector number
  81.     int    dos
  82.     mov    si,offset dgroup:pdsignature ; look for signature
  83.     push    cx
  84.     mov    cx,length pdsignature    ; length of string
  85.     mov    di,bx
  86.     add    di,3            ; sig starts 3 bytes from entry point
  87.     cld
  88.     repe    cmpsb            ; compare bytes
  89.     pop    cx
  90.     je    pdinit3            ; e = found a match
  91.     inc    cx
  92.     cmp    cx,80h            ; at end of range?
  93.     jna    pdinit1            ; na = not yet, try another int
  94.     stc                ; set carry for failure
  95.     jmp    pdret            ; take failure exit
  96.  
  97. pdinit3:mov    byte ptr PKTDRVI+1,cl    ; force in new PD interrupt, code mod
  98.                     ; find Ethernet address
  99.     mov    ah,pdgetinfo        ; get Packet Driver information
  100.     mov    al,0ffh
  101.     xor    bx,bx            ; optional handle
  102.     push    ds            ; this call changes ds and si
  103.     push    si
  104.     call    pktdrvr
  105.     pop    si
  106.     pop    ds
  107.     jc    pdret            ; c = failure
  108.     mov    if_type,dx        ; save details for access calls
  109.     mov    if_class,ch
  110.     mov    if_num,cl
  111.     mov    ah,pd_access        ; access packets
  112.     mov    al,ch            ; Ethernet class
  113.     mov    bx,dx            ; type
  114.     mov    dl,cl            ; interface number
  115.     mov    cx,notypelen        ; type length for notype
  116.     mov    si,offset dgroup:notype    ; TYPE (should match nothing)
  117.     mov    di,cs
  118.     mov    es,di
  119.     mov    di,offset pdrcvr    ; ES:DI is our Packet Driver receiver
  120.     call    pktdrvr
  121.     jc    pdret            ; c = failure
  122.     mov    bx,ax            ; put handle in bx
  123.     mov    ax,DGROUP        ; our data segment
  124.     mov    es,ax            ; segment of Ethernet address buffer
  125.     mov    di,[bp+4+2]        ; get offset of user's buffer
  126.     mov    cx,eaddr_len        ; length of address wanted
  127.     mov    ah,pd_get_address    ; get the ethernet address
  128.     push    bx            ; save handle
  129.     call    pktdrvr            ; get Ethernet address to es:di buf
  130.     pop    bx
  131.     pushf                ; save carry flag
  132.     mov    ah,pd_release        ; release this type, bx has handle
  133.     call    pktdrvr
  134.     popf                ; recover carry flag
  135. pdret:    mov    ax,1            ; return C status, 1 for success
  136.     jnc    pdret1
  137.     xor    ax,ax            ; 0 for failure
  138. pdret1:    pop    ds            ; success
  139.     pop    di
  140.     pop    si
  141.     pop    es
  142.     mov    sp,bp            ; restore stack
  143.     pop    bp            ; recover bp reg
  144.     ret
  145. _pdinit    endp
  146.  
  147. ; int pdinfo(& int version, & int class, & int pdtype, & int number,
  148. ;  & int functionality)
  149.     public    _pdinfo
  150. _pdinfo    proc    near
  151.     push    bp
  152.     mov    bp,sp
  153.     mov    ah,pdgetinfo        ; get Packet Driver information
  154.     mov    al,0ffh
  155.     xor    bx,bx            ; optional handle
  156.     push    ds            ; this call changes ds and si
  157.     push    si
  158.     call    pktdrvr
  159.     pop    si
  160.     pop    ds
  161.     jc    pdinfo1            ; c = failure
  162.     push    ax            ; save al for later use
  163.     mov    di,[bp+4+0]
  164.     mov    [di],bx            ; return version
  165.     mov    al,ch            ; class
  166.     xor    ah,ah
  167.     mov    di,[bp+4+2]
  168.     mov    [di],ax            ; return as an int
  169.     mov    di,[bp+4+4]
  170.     mov    [di],dx            ; type
  171.     mov    di,[bp+4+6]
  172.     xor    ch,ch
  173.     mov    [di],cx            ; interface number, as an int
  174.     pop    ax            ; recover al
  175.     mov    di,[bp+4+8]
  176.     xor    ah,ah
  177.     mov    [di],ax            ; functionality, as an int
  178. pdinfo1:mov    ax,1            ; C style exit status, 1 = success
  179.     jnc    pdinfo2            ; nc = success
  180.     xor    ax,ax            ; 0 = failure
  181. pdinfo2:pop    bp
  182.     ret
  183. _pdinfo    endp
  184.  
  185. ; int pdclose(int handle)
  186. ; Returns (in AX) 0 if successful, else 1.
  187.     public    _pdclose
  188. _pdclose    proc    near
  189.     push    bp
  190.     mov    bp,sp
  191.     mov    bx,[bp+4+0]        ; handle
  192.     mov    ah,pd_release        ; release_type
  193.     call    pktdrvr
  194.     mov    ax,1            ; assume success
  195.     jnc    pdclos1            ; nc = success
  196.     xor    ax,ax            ; 0 for failure
  197. pdclos1:pop    bp
  198.     ret
  199. _pdclose    endp
  200.  
  201. ; int pdaccess( char *type, typelen, int *handle)
  202. ; Register access for packet TYPE with the Packet Driver
  203.     public    _pdaccess
  204. _pdaccess proc    near
  205.     push    bp
  206.     mov    bp,sp
  207.     push    es
  208.     push    si
  209.     push    di
  210.     push    ds
  211.     push    es
  212.     mov    ax,dgroup        ; set up data segment addressibility
  213.     mov    ds,ax
  214.     mov    al,if_class        ; interface class
  215.     mov    bx,if_type        ; interface type (kind)
  216.     mov    dl,if_num        ; interface number
  217.     xor    dh,dh
  218.     mov    si,[bp+4+0]        ; get offset of packet TYPE buffer
  219.     mov    cx,[bp+4+2]        ; typelen (length of buf contents)
  220.     mov    di,cs            ; ES:DI is our Packet Driver receiver
  221.     mov    es,di
  222.     mov    di,offset pdrcvr    ; local receiver
  223.     mov    ah,pd_access        ; set access
  224.     call    pktdrvr
  225.     jc    pdacc1            ; c = failure
  226.     mov    si,[bp+4+4]        ; offset of handle
  227.     mov    [si],ax            ; return handle
  228. pdacc1:    mov    ax,1            ; C level status, 1 = success
  229.     jnc    pdacc2            ; nc = success
  230.     xor    ax,ax            ; 0 = failure
  231. pdacc2:    pop    es
  232.     pop    ds
  233.     pop    di
  234.     pop    si
  235.     pop    es
  236.     pop    bp
  237.     ret
  238. _pdaccess endp
  239.  
  240. ; int pkt_send( char *buffer, int length)
  241. ; returns 1 on success, 0 on failure
  242.     public    _pkt_send
  243. _pkt_send    proc    near
  244.     push    bp
  245.     mov    bp,sp
  246.     push    ds
  247.     push    si
  248.     mov    ax,dgroup        ; segment of outgoing buffer
  249.     mov    ds,ax            ;  will be DS:SI for Packet Driver
  250.     mov    si,[bp+4+0]        ; buffer's offset
  251.     mov    cx,[bp+4+2]        ; buffer's length
  252.     mov    ah,pd_send        ; send packet (buffer = ds:si)
  253.     call    pktdrvr            ; invoke Packet Driver
  254. pktsen1:mov    ax,1            ; return C level success (1)
  255.     jnc    pktsen2            ; nc = success
  256.     xor    ax,ax            ; else C level failure (0)
  257. pktsen2:pop    si
  258.     pop    ds
  259.          pop    bp
  260.     ret
  261. _pkt_send endp
  262.  
  263. ; Our Packet Driver receiver, far called only by the Packet Driver
  264. ; packet buffer:linked list
  265. ;    each link is    db    flag    ; 1 = free, 2 = in use, 4 = allocated
  266. ;                    ;  but not in use yet, 0 = end of buf
  267. ;                    ; 8 = read but not freed.
  268. ;            db    _pktwnum ; sequential number of pkt written
  269. ;            dw    count    ; length of data field
  270. ;            db count dup (?) ; the allocated data field
  271. ;    The head of the chain has a link like all others.
  272. ;    The end of the chain has a link with flag == 0 and count = -BUFISZE
  273. ;    to point to the beginning of the buffer (circular).
  274. ;    Packet buffer garbage collection is done after the PD transfers a
  275. ;    buffer to the application, and does so by relinking adjacent free
  276. ;    blocks.
  277. ; _pktbuf_wrote is used to remember the link where the last write occurred
  278. ; and should be initialized to the tail link to point the next write to
  279. ; the beginning of the buffer.
  280. ; The Packet Driver calls this first with AX = 0 to obtain a buffer pointer
  281. ; in ES:DI from us (0:0 if we refuse the pkt) with CX = packet size, and
  282. ; again with AX = 1 to post completion.
  283. ; I'm going to turn off interrupts around this code in an attempt to interlock
  284. ; access coherently. It may need to be removed later.
  285.  
  286. pdrcvr    proc    far            ; dummy Packet Driver receiver
  287.     or    ax,ax            ; kind of upcall from PD
  288.     jz    pdrcvr1            ; z = first, get-a-buffer
  289.     ; Second upcall, packet has xfered, ds:si set by PD to xfered buffer
  290.     pushf                ; save interrupt status
  291.     cli                ; interrupts off
  292.      push    ds
  293.     push    si
  294.     push    bx
  295.     push    ax            ; assume ds:si is wrong
  296.      mov    ax,dgroup
  297.     mov    ds,ax            ; set ds to our data segment
  298.     mov    si,pendingpkt        ; offset of pkt being confirmed
  299.     or    si,si            ; is it legal (from first upcall)?
  300.     jz    pdrcvr10        ; z = no, ignore this call
  301.     sub    si,linksize        ; backup to link info
  302.     mov    byte ptr [si].flag,2    ; flag = 2 for buffer is now ready
  303.     mov    al,_pktwnum         ; write packet number sequencer
  304.     mov    [si].bufnum,al
  305.     inc    _pktwnum        ; ready it for next write
  306.  
  307.     mov    si,pktbufoff         ; start of packet buffer
  308.     mov    al,[si]            ; flags byte
  309.                     ; join contiguous free links
  310. pdrcvr8:cmp    al,1            ; link is free?
  311.     jne    pdrcvr9            ; ne = no, look for a free link
  312.     mov    bx,[si].count        ; count of this link
  313.     cmp    byte ptr [bx+si+linksize],1 ; is next link free?
  314.     jne    pdrcvr9            ; ne = no, look for free link
  315.     mov    ax,[bx+si+linksize].count ; count taken from next link
  316.     add    ax,linksize        ;  plus the next link's info field
  317.     add    [si].count,ax        ; add it to this count (merge links)
  318.     jmp    short pdrcvr8        ; reexamine this new longer link
  319.  
  320. pdrcvr9:add    si,[si].count        ; look at next link (add count)
  321.     add    si,linksize        ; and link info
  322.     mov    al,[si].flag        ; get link flags
  323.     or    al,al            ; end of list?
  324.     jnz    pdrcvr8            ; nz = no
  325.     mov    pendingpkt,0        ; say we are done with second upcall
  326. pdrcvr10:pop    ax
  327.     pop    bx
  328.     pop    si
  329.     pop    ds
  330.     popf
  331.     ret                ; yes, quit
  332.  
  333.  
  334. pdrcvr1:pushf
  335.     cli
  336.     push    ds            ; First upcall, provide buf ptr
  337.     push    dx
  338.     push    cx
  339.     mov    di,dgroup        ; get local addressibility
  340.     mov    ds,di
  341.     mov    es,di            ; packet buffer is in same group
  342.     mov    di,_pktbuf_wrote    ; where last write occurred
  343.     or    di,di            ; NULL?
  344.     jz    pdrcvr4            ; z = yes, write nothing
  345.     mov    dl,100            ; retry counter, breaks endless loops
  346.     cmp    [di].flag,1        ; is this place now free?
  347.     je    pdrcvr5            ; e = yes, use it
  348.  
  349. pdrcvr2:add    di,[di].count        ; point at next link (add count and
  350.     add    di,linksize        ;  link overhead)
  351.     dec    dl            ; loop breaker count down
  352.     or    dl,dl
  353.     jz    pdrcvr4            ; z = in an endless loop, exit
  354.     cmp    [di].flag,1        ; is this link free (1)?
  355.     je    pdrcvr5            ; e = yes, setup storage
  356.     cmp    di,_pktbuf_wrote     ; have we come full circle?
  357.     jne    pdrcvr2            ; ne = no, keep looking
  358. pdrcvr4:pop    cx
  359.     pop    dx
  360.     pop    ds            ; failure or buffer not available (0)
  361.     xor    ax,ax            ; return what we received in ax
  362.     xor    di,di            ; return ES:DI as null to reject
  363.     mov    es,di
  364.     popf
  365.     ret
  366.                     ; this link is free
  367. pdrcvr5:cmp    cx,ETH_MSS+40+12 +20    ; LARGEST PACKET WE ACCEPT
  368.     ja    pdrcvr4            ; a = yes, decline it
  369.     add    cx,2            ; defense for 8/16 bit xfr mistakes
  370.     mov    ax,[di].count        ; length of available data space
  371.     cmp    ax,cx            ; cx is incoming size, enough space?
  372.     jl    pdrcvr2            ; l = no, go to next link
  373.     mov    [di].flag,4        ; mark link flag as being alloc'd (4)
  374.     mov    dh,_pktwnum         ; write pkt sequencer number
  375.     mov    [di].bufnum,dh        ; don't inc this til PD is done
  376.     mov    _pktbuf_wrote,di    ; remember where we wrote last
  377.                     ; leave whole area allocated here
  378.     sub    ax,cx            ; allocated minus incoming packet
  379.     cmp    ax,60+linksize        ; enough for new link and miminal pkt?
  380.     jl    pdrcvr6            ; l = not enough for next pkt
  381.     mov    [di].count,cx        ; update space really used
  382.     push    di            ; save this link pointer
  383.     add    di,linksize        ; plus current link info
  384.     add    di,cx            ; plus space used = new link point
  385.     sub    ax,linksize        ; available minus new link info
  386.     mov    [di].flag,1        ; mark new link as free (1)
  387.     mov    [di].count,ax        ; size of new free data area
  388.     pop    di            ; return to current link
  389. pdrcvr6:add    di,linksize        ; point at data portion for Pkt Drvr
  390.     mov    pendingpkt,di        ; preserve in case host does not
  391.     xor    ax,ax            ; return what we received in ax
  392.     pop    cx
  393.     pop    dx
  394.     pop    ds            ; ES:DI is the pkt buffer address
  395.     popf
  396.     ret
  397. pdrcvr    endp
  398. _TEXT    ends
  399.         end
  400.  
  401.